package com.start.avue.convert;


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.start.avue.configs.StartAvueMapperConfig;
import com.start.avue.mapper.AvueDefaultMapper;
import com.start.avue.mapper.StartAvueMapper;
import com.start.common.exceptions.StartBusException;
import com.start.common.tools.ClassTools;
import com.start.common.tools.SpringContextTools;
import com.start.common.tools.StartRequestTools;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.servlet.http.HttpServletRequest;
import java.util.*;

public class AvueFormMapperConvert {
    private static final Logger logger = LoggerFactory.getLogger(AvueFormMapperConvert.class);
    private final Map<String, String> headers;
    private final String startHomeUrl;
    private final Map<String, Class<? extends StartAvueMapper>> avueMapper;
    private Class<? extends StartAvueMapper> globalDefaultMapper;


    public Class<? extends StartAvueMapper> getGlobalDefaultMapper() {
        return globalDefaultMapper;
    }

    public AvueFormMapperConvert(String startHomeUrl, Map<String, String> headers) {
        this(startHomeUrl, null, headers);
    }

    public static AvueFormMapperConvert create(String startHomeUrl, HttpServletRequest request) {
        Map<String, String> map = StartRequestTools.getHeaders(request);
        return new AvueFormMapperConvert(startHomeUrl, map);
    }


    public static AvueFormMapperConvert create(HttpServletRequest request, String headerKey) {
        Map<String, String> map = StartRequestTools.getHeaders(request);
        String homeUrl = request.getHeader(headerKey);
        return new AvueFormMapperConvert(homeUrl, map);
    }

    public AvueFormMapperConvert(String startHomeUrl, Map<String, Class<? extends StartAvueMapper>> mappers, Map<String, String> headers) {
        this(startHomeUrl, mappers, headers, AvueDefaultMapper.class);
    }

    public AvueFormMapperConvert(String startHomeUrl, Map<String, Class<? extends StartAvueMapper>> mappers, Map<String, String> headers, Class<? extends StartAvueMapper> globalDefaultMapper) {
        if (mappers == null || mappers.isEmpty()) {
            mappers = StartAvueMapperConfig.getInstance().getConfigMapper();
        }
        this.startHomeUrl = startHomeUrl;
        globalDefaultMapper = AvueDefaultMapper.class;
        this.headers = headers;
        this.globalDefaultMapper = globalDefaultMapper;
        this.avueMapper = mappers;
    }

    public List<StartAvueMapper> getAvueMapper(JSONObject formOption) {
        if (!formOption.containsKey("column")) {
            return new ArrayList<>();
        }

        JSONArray column = formOption.getJSONArray("column");
        List<StartAvueMapper> result = new ArrayList<>(column.size());
        for (int i = column.size() - 1; i >= 0; i--) {
            JSONObject col = column.getJSONObject(i);
            StartAvueMapper avueColMapper = getAvueColMapper(col);
            result.add(avueColMapper);
        }
        return result;
    }

    public Map<String, StartAvueMapper> getAvueMapperPropMap(JSONObject formOption) {
        if (!formOption.containsKey("column")) {
            return new HashMap<>();
        }

        JSONArray column = formOption.getJSONArray("column");
        HashMap<String, StartAvueMapper> result = new HashMap<>(column.size());
        for (int i = column.size() - 1; i >= 0; i--) {
            JSONObject col = column.getJSONObject(i);
            StartAvueMapper avueColMapper = getAvueColMapper(col);
            result.put(col.getString("prop"), avueColMapper);
        }
        return result;
    }

    public StartAvueMapper getAvueColMapper(JSONObject col) {
        String columnComponentName = getColumnComponentName(col);
        Class<? extends StartAvueMapper> mapperClazz = avueMapper.getOrDefault(columnComponentName, globalDefaultMapper);
        StartAvueMapper mapper = ClassTools.createObject(mapperClazz);
        SpringContextTools.autowire(mapper);
        mapper.init(startHomeUrl, col, headers);
        return mapper;
    }

    public static String getColumnComponentName(JSONObject col) {
        String component = col.getString("component");
        if (StringUtils.isNotBlank(component)) {
            return component;
        }
        String type = col.getString("type");
        if (StringUtils.isNotBlank(type)) {
            return type;
        }
        return "input";
    }

    public List<JSONObject> convertDataToLabel(JSONObject formOption, List<JSONObject> dataList) {
        List<StartAvueMapper> mappers = getAvueMapper(formOption);
        return convertDataToLabel(mappers, dataList);
    }

    public List<JSONObject> convertDataToLabel(List<StartAvueMapper> mappers, List<JSONObject> dataList) {
        if (mappers == null) {
            throw new StartBusException("mapperMap is not null");
        }
        List<JSONObject> result = new ArrayList<>();
        for (int i = dataList.size() - 1; i > -1; i--) {
            JSONObject jsonObject = convertDataToLabel(mappers, dataList.get(i));
            result.add(jsonObject);
        }
        Collections.reverse(result);
        return result;
    }


    /**
     * 数据转换
     *
     * @param formOption 云表单配置
     * @param data       需要转换的数据
     * @return
     */
    public JSONObject convertDataToLabel(JSONObject formOption, JSONObject data) {
        List<StartAvueMapper> mappers = getAvueMapper(formOption);
        return convertDataToLabel(mappers, data);
    }

    public JSONObject convertDataToLabel(List<StartAvueMapper> mappers, JSONObject data) {
        JSONObject result = new JSONObject();
        for (int i = mappers.size() - 1; i > -1; i--) {
            StartAvueMapper mapper = mappers.get(i);
            String key = mapper.getColumnOption().getString("prop");
            Object val = data.get(key);
            if (val == null) {
                result.put(key, "");
                continue;
            }
            Object value = mapper.valueToLabel(val);
            result.put(key, value);
        }
        return result;
    }

    public JSONArray convertDataToLabel(List<StartAvueMapper> mappers, JSONArray jsonArrayData) {
        JSONArray result = new JSONArray();
        int size = jsonArrayData.size();
        for (int i = 0; i < size; i++) {
            JSONObject jsonObject = jsonArrayData.getJSONObject(i);
            JSONObject item = convertDataToLabel(mappers, jsonObject);
            result.add(item);
        }
        return result;

    }
}
